package com.dxf.database.dbDao.impl;

import com.dxf.database.dbDao.DBMetaData;
import com.dxf.database.dbInfo.DataBase;
import com.dxf.entity.Column;
import com.dxf.entity.Table;
import com.dxf.utils.DriverManagerFactory;
import com.dxf.utils.PropertiesUtils;
import com.dxf.utils.StringUtils;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 获取数据库的基本信息
 */
public class DBMetaDataImpl implements DBMetaData {

    @Override
    public List<Table> getAllTables(DataBase dbBase) throws Exception {
        return getDbInfo(dbBase,null);
    }

    /**
     * 获取一个table的信息
     * @param tableName
     * @return
     * @throws Exception
     */
    @Override
    public List<Table> getTable(DataBase dbBase,String tableName) throws Exception {
        return getDbInfo(dbBase,tableName);
    }


    /**
     * 获取数据库中的表和字段,构造实体类
     * table对象
     * 1 参数
     * DataBase 数据库对象
     * 2 操作步骤
     * 2.1 获取了解
     * 2.2 获取DatabaseMetaData
     * 2.3 获取当前数据库中所有表信息
     * 2.4 获取每个表中所有字段
     * 2.5 封装到java对象
     */
    public static List<Table> getDbInfo(DataBase db,String TABLE_NAME) throws Exception {
        //获取连接
        Connection connection = DriverManagerFactory.getConnection(db);
        //获取元数据
        DatabaseMetaData metaData = connection.getMetaData();

        //获取所有表信息   getTables()检索给定目录中可用表的描述
        ResultSet tables = metaData.getTables(null, null, TABLE_NAME, new String[]{"TABLE"});
        ArrayList<Table> list = new ArrayList<>();

        while (tables.next()) {
            Table table = new Table();
          /*  private String name;//表名称
            private String name2;//处理后的表名称
            private String comment;//介绍
            private String key;// 主键列
            private List<Column> columns;//列集合*/
            //1 表名
            String tableName = tables.getString("TABLE_NAME");//bs_User
            //2 处理后的类名称
            String className = removePrefix(tableName);
            //3 表述
            String remarks =    tables.getString("REMARKS");

            //4 主键()
            ResultSet primaryKeys = metaData.getPrimaryKeys(null, null, tableName);
            String keys = "";
            while (primaryKeys.next()) {
                String keyName = primaryKeys.getString("COLUMN_NAME");
                keys += keyName;
            }

            //5 表中所有字段内容
            ResultSet columns = metaData.getColumns(null, null, tableName, null);
            //多个列
            ArrayList<Column> columnList = new ArrayList<>();
            while (columns.next()) {
                Column column = new Column();
                //构造column对象
               /* private String columnName;//列名称
                private String columnName2;//列名称(处理后的列名称)
                private String columnType;//列类型java类型
                private String columnDbType;//列数据库类型
                private String columnComment;//列备注
                private String columnKey;//是否是主键*/
                String columnName = columns.getString("COLUMN_NAME");//列名
                String attName = StringUtils.toJavaVariableName(columnName);//类属性名
                String attName2 = StringUtils.getUpperFirstName(attName);//类属性名首字母大写
                String dbType = columns.getString("TYPE_NAME");//sql中的类型:varchar,DateTime
                String javaType = PropertiesUtils.applicationMap.get(dbType);//java中的类型
                String defaultValue= PropertiesUtils.applicationMap.get(javaType);
                String colunmRemarks = columns.getString("REMARKS");//列的备注
                String columnSize = columns.getString("COLUMN_SIZE");//列长度
                /**
                 *  0 (columnNoNulls) - 该列不允许为空
                 *  1 (columnNullable) - 该列允许为空
                 *  2 (columnNullableUnknown) - 不确定该列是否为空
                 */
                int able = columns.getInt("NULLABLE");//是否为空
                if (able==0){
                    column.setIsRequired("true");
                }else {
                    column.setIsRequired("false");
                }

                String columnKey = "false";
                if(keys.equals(columnName)){
                    //是主键
                    columnKey = "true";
                }
                /*if (StringUtils.contains(columnName, keys.split(","))) {
                    //是主键
                    columnKey = "true";
                }*/



                //封装
                column.setColumnComment(colunmRemarks==null? "":colunmRemarks);
                column.setColumnKey(columnKey);
                column.setColumnDbType(dbType);
                column.setColumnName(columnName);
                column.setColumnName2(attName);
                column.setColumnName3(attName2);
                column.setColumnType(javaType);
                column.setColumnSize(columnSize);
                column.setDefaultValue(defaultValue);

                columnList.add(column);
            }

            columns.close();

            //6封装
            table.setName(tableName);
            table.setName2(className);
            table.setComment(remarks==null? "" : remarks);
            table.setKey(keys);
            table.setColumns(columnList);
            list.add(table);
        }
        tables.close();
        connection.close();
        return list;
    }

    /**
     * 根据表的名字,移除前缀后 驼峰命名后的 类名字
     *
     * @param tableName
     * @return
     */
    public static String removePrefix(String tableName) {

        String[] prefixs = PropertiesUtils.applicationMap.get("tableRemovePrefixes").split(",");//读取配置文件
        String temp = tableName;

        //tb_,co_,pe_,bs_
        for (String prefix : prefixs) {
            temp = StringUtils.removePrefix(temp, prefix, true);//true 是否忽略大小写,是
        }

        return StringUtils.makeAllWordFirstLetterUpperCase2(temp);
    }

}
